// Copyright (c) MatrixFramework. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
using MatrixFramework.Photos.Domain.Shared.Enums;
using MatrixFramework.Photos.Domain.ValueObjects;
using MatrixFramework.Core.Results;

namespace MatrixFramework.Photos.Domain.Entities;

/// <summary>
/// 照片领域实体
/// 表示系统中的单个照片或视频文件
/// </summary>
public class Photo : FullAuditedAggregateRoot<Guid>, IMultiTenant
{
    /// <summary>
    /// 租户ID
    /// </summary>
    public virtual Guid? TenantId { get; protected set; }

    /// <summary>
    /// 照片文件名
    /// </summary>
    [Required]
    [MaxLength(500)]
    public virtual string FileName { get; protected set; } = string.Empty;

    /// <summary>
    /// 原始文件名
    /// </summary>
    [Required]
    [MaxLength(500)]
    public virtual string OriginalFileName { get; protected set; } = string.Empty;

    /// <summary>
    /// 文件扩展名
    /// </summary>
    [Required]
    [MaxLength(50)]
    public virtual string Extension { get; protected set; } = string.Empty;

    /// <summary>
    /// MIME类型
    /// </summary>
    [Required]
    [MaxLength(200)]
    public virtual string ContentType { get; protected set; } = string.Empty;

    /// <summary>
    /// 文件大小（字节）
    /// </summary>
    public virtual long FileSize { get; protected set; }

    /// <summary>
    /// 文件哈希值（用于去重）
    /// </summary>
    [Required]
    [MaxLength(100)]
    public virtual string FileHash { get; protected set; } = string.Empty;

    /// <summary>
    /// 存储路径
    /// </summary>
    [Required]
    [MaxLength(1000)]
    public virtual string StoragePath { get; protected set; } = string.Empty;

    /// <summary>
    /// 访问URL
    /// </summary>
    [MaxLength(2000)]
    public virtual string? AccessUrl { get; protected set; }

    /// <summary>
    /// 下载URL
    /// </summary>
    [MaxLength(2000)]
    public virtual string? DownloadUrl { get; protected set; }

    /// <summary>
    /// 缩略图URL
    /// </summary>
    [MaxLength(2000)]
    public virtual string? ThumbnailUrl { get; protected set; }

    /// <summary>
    /// 照片类型
    /// </summary>
    public virtual PhotoType PhotoType { get; protected set; }

    /// <summary>
    /// 处理状态
    /// </summary>
    public virtual PhotoProcessingStatus ProcessingStatus { get; protected set; }

    /// <summary>
    /// 处理时间
    /// </summary>
    public virtual DateTime? ProcessedAt { get; protected set; }

    /// <summary>
    /// 照片标题
    /// </summary>
    [MaxLength(500)]
    public virtual string? Title { get; protected set; }

    /// <summary>
    /// 照片描述
    /// </summary>
    [MaxLength(2000)]
    public virtual string? Description { get; protected set; }

    /// <summary>
    /// 照片拍摄时间
    /// </summary>
    public virtual DateTime? TakenTime { get; protected set; }

    /// <summary>
    /// 是否为收藏
    /// </summary>
    public virtual bool IsFavorite { get; protected set; }

    /// <summary>
    /// 是否公开访问
    /// </summary>
    public virtual bool IsPublic { get; protected set; }

    /// <summary>
    /// 访问次数
    /// </summary>
    public virtual int AccessCount { get; protected set; }

    /// <summary>
    /// 下载次数
    /// </summary>
    public virtual int DownloadCount { get; protected set; }

    /// <summary>
    /// 分享次数
    /// </summary>
    public virtual int ShareCount { get; protected set; }

    /// <summary>
    /// 照片元数据
    /// </summary>
    public virtual PhotoMetadata? Metadata { get; protected set; }

    /// <summary>
    /// 照片标签
    /// </summary>
    public virtual ICollection<PhotoTag> Tags { get; protected set; } = new List<PhotoTag>();

    /// <summary>
    /// 照片人物
    /// </summary>
    public virtual ICollection<PhotoPerson> People { get; protected set; } = new List<PhotoPerson>();

    /// <summary>
    /// 相册关联
    /// </summary>
    public virtual ICollection<PhotoAlbum> Albums { get; protected set; } = new List<PhotoAlbum>();

    #region 构造函数

    /// <summary>
    /// 参数化构造函数
    /// </summary>
    /// <param name="id">照片ID</param>
    /// <param name="tenantId">租户ID</param>
    /// <param name="fileName">文件名</param>
    /// <param name="originalFileName">原始文件名</param>
    /// <param name="extension">扩展名</param>
    /// <param name="contentType">MIME类型</param>
    /// <param name="fileSize">文件大小</param>
    /// <param name="fileHash">文件哈希</param>
    /// <param name="storagePath">存储路径</param>
    public Photo(
        Guid id,
        Guid? tenantId,
        string fileName,
        string originalFileName,
        string extension,
        string contentType,
        long fileSize,
        string fileHash,
        string storagePath) : base(id)
    {
        TenantId = tenantId;
        FileName = fileName;
        OriginalFileName = originalFileName;
        Extension = extension;
        ContentType = contentType;
        FileSize = fileSize;
        FileHash = fileHash;
        StoragePath = storagePath;
        PhotoType = DeterminePhotoType(extension);
        ProcessingStatus = PhotoProcessingStatus.Pending;
        AccessCount = 0;
        DownloadCount = 0;
        ShareCount = 0;
        IsFavorite = false;
        IsPublic = false;
    }

    /// <summary>
    /// 无参构造函数（用于EF Core）
    /// </summary>
    protected Photo()
    {
        Tags = new List<PhotoTag>();
        People = new List<PhotoPerson>();
        Albums = new List<PhotoAlbum>();
    }

    #endregion

    #region 业务方法

    /// <summary>
    /// 开始处理照片
    /// </summary>
    public virtual Result StartProcessing()
    {
        if (ProcessingStatus != PhotoProcessingStatus.Pending)
        {
            return Result.Failure("照片处理状态不是待处理状态");
        }

        ProcessingStatus = PhotoProcessingStatus.Processing;
        return Result.Success();
    }

    /// <summary>
    /// 完成照片处理
    /// </summary>
    /// <param name="accessUrl">访问URL</param>
    /// <param name="thumbnailUrl">缩略图URL</param>
    /// <param name="metadata">元数据</param>
    public virtual Result CompleteProcessing(
        string? accessUrl = null,
        string? thumbnailUrl = null,
        PhotoMetadata? metadata = null)
    {
        if (ProcessingStatus != PhotoProcessingStatus.Processing)
        {
            return Result.Failure("照片处理状态不是处理中状态");
        }

        ProcessingStatus = PhotoProcessingStatus.Completed;
        ProcessedAt = DateTime.UtcNow;

        if (!string.IsNullOrEmpty(accessUrl))
            AccessUrl = accessUrl;

        if (!string.IsNullOrEmpty(thumbnailUrl))
            ThumbnailUrl = thumbnailUrl;

        if (metadata != null)
            Metadata = metadata;

        return Result.Success();
    }

    /// <summary>
    /// 标记处理失败
    /// </summary>
    /// <param name="errorMessage">错误信息</param>
    public virtual Result FailProcessing(string errorMessage)
    {
        if (ProcessingStatus != PhotoProcessingStatus.Processing)
        {
            return Result.Failure("照片处理状态不是处理中状态");
        }

        ProcessingStatus = PhotoProcessingStatus.Failed;
        return Result.Success();
    }

    /// <summary>
    /// 更新基本信息
    /// </summary>
    /// <param name="title">标题</param>
    /// <param name="description">描述</param>
    /// <param name="takenTime">拍摄时间</param>
    public virtual Result UpdateBasicInfo(string? title, string? description, DateTime? takenTime)
    {
        Title = title;
        Description = description;
        TakenTime = takenTime;
        return Result.Success();
    }

    /// <summary>
    /// 设置收藏状态
    /// </summary>
    /// <param name="isFavorite">是否收藏</param>
    public virtual Result SetFavorite(bool isFavorite)
    {
        IsFavorite = isFavorite;
        return Result.Success();
    }

    /// <summary>
    /// 设置公开状态
    /// </summary>
    /// <param name="isPublic">是否公开</param>
    public virtual Result SetPublic(bool isPublic)
    {
        IsPublic = isPublic;
        return Result.Success();
    }

    /// <summary>
    /// 增加访问次数
    /// </summary>
    public virtual void IncrementAccessCount()
    {
        AccessCount++;
    }

    /// <summary>
    /// 增加下载次数
    /// </summary>
    public virtual void IncrementDownloadCount()
    {
        DownloadCount++;
    }

    /// <summary>
    /// 增加分享次数
    /// </summary>
    public virtual void IncrementShareCount()
    {
        ShareCount++;
    }

    /// <summary>
    /// 添加标签
    /// </summary>
    /// <param name="tag">标签</param>
    public virtual Result AddTag(PhotoTag tag)
    {
        if (Tags.Any(t => t.Name.Equals(tag.Name, StringComparison.OrdinalIgnoreCase)))
        {
            return Result.Failure("标签已存在");
        }

        Tags.Add(tag);
        return Result.Success();
    }

    /// <summary>
    /// 移除标签
    /// </summary>
    /// <param name="tagName">标签名称</param>
    public virtual Result RemoveTag(string tagName)
    {
        var tag = Tags.FirstOrDefault(t => t.Name.Equals(tagName, StringComparison.OrdinalIgnoreCase));
        if (tag == null)
        {
            return Result.Failure("标签不存在");
        }

        Tags.Remove(tag);
        return Result.Success();
    }

    /// <summary>
    /// 添加人物
    /// </summary>
    /// <param name="person">人物</param>
    public virtual Result AddPerson(PhotoPerson person)
    {
        People.Add(person);
        return Result.Success();
    }

    #endregion

    #region 私有方法

    /// <summary>
    /// 根据扩展名确定照片类型
    /// </summary>
    /// <param name="extension">文件扩展名</param>
    /// <returns>照片类型</returns>
    private static PhotoType DeterminePhotoType(string extension)
    {
        var ext = extension.ToLowerInvariant();

        if (MatrixFramework.Photos.Domain.Shared.Constants.PhotoConstants.SupportedRawFormats.Contains(ext))
        {
            return PhotoType.Raw;
        }
        else if (MatrixFramework.Photos.Domain.Shared.Constants.PhotoConstants.SupportedImageFormats.Contains(ext))
        {
            if (ext == ".gif")
                return PhotoType.Gif;
            else
                return PhotoType.Image;
        }
        else if (MatrixFramework.Photos.Domain.Shared.Constants.PhotoConstants.SupportedVideoFormats.Contains(ext))
        {
            return PhotoType.Video;
        }

        return PhotoType.Unknown;
    }

    #endregion
}